// Thread wrapper class
// Copyright 2004 (C) Ralph Thomas

#ifndef THREAD_H
#define THREAD_H

#include <boost/function.hpp>

namespace util {
	//
	/// An instance of this thread class represents a thread which can be
	/// assigned work to do.
	//
	class thread {
		class threadImpl* _impl;
	  public:
		//
		// thread()
		//
		/// Constructor. Create a new thread, ready and waiting for
		/// work to be submitted, via adoptWork.
		///
		/// \sa adoptWork
		//
		thread();
		//
		// ~thread()
		//
		/// Destroy this thread, and leave any work which it might be
		/// doing in an indeterminate state.
		//
		virtual ~thread();
		//
		// class work
		//
		/// The work class represents a unit of work for the thread to
		/// do. Actual work implementations need to implement the pure
		/// virtual "doWork" member. Any parameters which are required
		/// for this work should probably be setup in the work subclass
		/// which you are implementing. Remember that the doWork member
		/// will be run by a different thread, thus you must be careful
		/// with locking whatever resources the doWork implementation
		/// uses.
		///
		/// When the work has been performed, the work object will be
		/// deleted. This destructor is also called by the other thread.
		/// Once the object has been destroyed, the thread will either
		/// go onto the next work item, or wait for one to be submitted.
		//
		class work {
		  public:
			//
			// ~work()
			//
			/// Virtual destructor. Note that this will be called
			/// by the thread!
			//
			virtual ~work();
			//
			// void doWork()
			//
			/// This member gets called by the thread and should do
			/// all the work which needs to be done by the thread.
			/// Please be careful to lock any shared resources you
			/// use in the implementation of this member.
			//
			virtual void doWork() = 0;
			//
			// enum priority
			//
			/// This enumeration provides the different priorities
			/// for items of work in the queue. The thread will
			/// always execute the highest priority item of work
			/// next.
			//
			enum priority {
				//
				/// This work was requested directly by the
				/// user, and is therefore the MOST IMPORTANT
				/// thing for this thread to do.
				//
				kWorkPriorityUser,
				//
				/// This work was reqested as some regular
				/// thing to do, which isn't very important.
				//
				kWorkPriorityRegular
			};
			//
			// virtual priority getPriority() const
			//
			/// This method returns the priority of this item of
			/// work. The work priority is used to determine which
			/// item of work to do next. The work items are sorted
			/// by highest priority, and then by the time the item
			/// of work was submitted (most recent better).
			///
			/// \return	the priority of this work item.
			//
			virtual priority getPriority() const = 0;
		};
		//
		/// This pre-made work class takes a boost::function and
		/// executes that.
		//
		class boostWork : public work {
			boost::function<void ()> _work;
		  public:
			explicit boostWork( const boost::function<void ()>& fn );
			virtual ~boostWork();
			virtual void doWork();
			virtual priority getPriority() const;
		};
		//
		// void adoptWork( work* theWork )
		//
		/// Add the given work object to the list of items of work to
		/// do. There is no timescale as to when the work will be
		/// completed, and no feedback given when it is done (other
		/// than that which may be in place in the work object you
		/// supply).
		///
		/// Ownership of the given work object is transferred to this
		/// thread object - you should not attempt to access (or delete
		/// or anything) the given work object after making this call.
		///
		/// The thread will figure out which work to do in this order:
		///  - priority
		///  - time work was submitted (most recent first)
		///
		/// This means that more recent user actions are dealt with
		/// before older actions (which is the correct way around, no
		/// point in getting mail headers for mail which has already
		/// been scrolled past).
		///
		/// \param	theWork	a work object describing the work to be
		///		performed.
		//
		virtual void adoptWork( work* theWork );
		//
		/// As adoptWork, but adopting a boost::function.
		///
		/// \param	theWork	a boost::function to execute.
		//
		virtual void adoptWork( const boost::function<void()>& theWork );
	};
};

#endif

